#pragma once
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <cstring>
#include "Log.hpp"
#include "Common.hpp"
#include "InetAddr.hpp"

using namespace LogModule;
namespace SocketModule
{
   
    class Socket;
    using SockPtr = std::shared_ptr<Socket>;
    class Socket
    {
    public:
        virtual ~Socket() = default;
        virtual void SocketOrDie() = 0;
        virtual void SetSocketOption() = 0;
        virtual bool Bind(int port) = 0;
        virtual bool Listen() = 0;
        virtual SockPtr Accepter(InetAddr *client) = 0;
        virtual void close() = 0;
        virtual int Recv(std::string *out) = 0; // 接收数据
        virtual int Send(std::string &in) = 0;  // 发送数据
        virtual int fd()=0;
        // 提供一个创建listen socket的接口
        void BuildTcpSockeMethod(int port)
        {
            SocketOrDie();
            SetSocketOption();
            Bind(port);
            Listen();
        }
    };

    class TcpSocket : public Socket
    {
    public:
        TcpSocket(int sockfd) : _sockfd(sockfd) {}
        TcpSocket() : _sockfd(-1) {}
        void SocketOrDie() override
        {
            _sockfd = socket(AF_INET, SOCK_STREAM, 0);
            if (_sockfd < 0)
            {
                LOG(LogLevel::ERROR) << "create socket failed";
                Die(SOCKET_ERR);
            }
            LOG(LogLevel::INFO) << "create socket success";
        }
        void SetSocketOption() override
        {
        }

        bool Bind(int port) override
        {
            // struct sockaddr_in addr;
            // ::bzero(&addr, sizeof(addr));
            // addr.sin_family = AF_INET;
            // addr.sin_port = htons(port);
            // addr.sin_addr.s_addr = htonl(INADDR_ANY);
            InetAddr addr(port);
            // int n = bind(_sockfd, CONV(&addr), sizeof(addr));
            int n = bind(_sockfd, addr.NetAddr(), addr.NetAddrLen());
            if (n < 0)
            {
                LOG(LogLevel::ERROR) << "bind socket error";
                Die(BIND_ERR);
            }
            LOG(LogLevel::INFO) << "bind socket success";
            return true;
        }
        bool Listen() override
        {
            int n = listen(_sockfd, 10);
            if (n < 0)
            {
                LOG(LogLevel::ERROR) << "listen socket error";
                Die(LISTEN_ERR);
            }
            LOG(LogLevel::INFO) << "listen socket success";
            return true;
        }
        // 接受一个连接
        SockPtr Accepter(InetAddr *client) override
        {
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            int newsockfd = ::accept(_sockfd, CONV(&peer), &len);
            if (newsockfd < 0)
            {
                LOG(LogLevel::ERROR) << "accept socket error";
                Die(ACCEPT_ERR);
            }
            LOG(LogLevel::INFO) << "accept socket success";
            client->SetAddr(peer, len);
            return std::make_shared<TcpSocket>(newsockfd); // 返回一个TcpSocket对象
        }
        void close() override
        {
            ::close(_sockfd);
        }

        int Recv(std::string *out) override
        {
            char buffer[1024];
            auto n = ::recv(_sockfd, buffer, sizeof(buffer)-1, 0);
            if(n>0)
            {
                buffer[n]=0;
                *out+=buffer;
            }
            return n;
        }

        int Send(std::string &in)
        {
            auto n =::send(_sockfd,in.c_str(),in.size(),0);
            return n;
        }
        int fd() override
        {
            return _sockfd;
        }

    private:
        int _sockfd;
    };
}
